﻿
//{{{ file documentation -------------------------------------------------------

/*!
 * @file     mainwindow.cpp
 * @brief    dicodor mainwindow class implémentation
 */

//}}} --------------------------------------------------------------------------
//{{{ includes / predeclarations -----------------------------------------------

// @(#) $Id: mainwindow.cpp 53 2012-05-23 13:56:41Z nsouchon-dico@altern.org $

#include "mainwindow.h"
#include "moc_mainwindow.cpp"

#include "messages.h"
#include "ui_orthowindow.h"

#include <QtGui/QDesktopWidget>
#include <QtGui/QFileDialog>
#include <QtGui/QTextDocumentWriter>
#include <QtGui/QProgressBar>

//}}} --------------------------------------------------------------------------
//{{{ MainWindow ---------------------------------------------------------------
//}}} --------------------------------------------------------------------------
//{{{ .MainWindow (const QString & documentPath, QWidget * parent) -------------

MainWindow::MainWindow (const QString & documentPath, QWidget * parent) :
    QMainWindow (parent),
    ui (new Ui::MainWindow),
    m_config (new Config (this)),
    m_documentPath (documentPath)
{
    ui->setupUi (this);

    m_ortho = new Ortho (this);

    m_messages.clear ();

    initTests ();
    initWindow ();
    initMenu ();
    initToolbar ();
    initDocument ();
    initConnect ();

    m_ortho->init ();   // initialisation : peut échouer

    open (documentPath);
}

//}}} --------------------------------------------------------------------------
//{{{ .~MainWindow () ----------------------------------------------------------

MainWindow::~MainWindow ()
{
    delete ui;
}

//}}} --------------------------------------------------------------------------
//{{{ .void    initTests () ----------------------------------------------------

void MainWindow::initTests ()
{
    qDebug () << tr ("\n Vérification des formats de sauvegarde de texte supportés :");
    QList<QByteArray> formats (QTextDocumentWriter::supportedDocumentFormats ());
    if (formats.contains (QByteArray ("ODF")))
    {
        qDebug () << tr ("Le format ODF est supporté.");
    }
}

//}}} --------------------------------------------------------------------------
//{{{ .void    initWindow () ---------------------------------------------------

void MainWindow::initWindow ()
{
    // centrage sur l'écran
    const QDesktopWidget   dw;
    const QRect          & screen (dw.screenGeometry ());
    setGeometry (
            screen.center ().x () - width () / 2,
            screen.center ().y () - height () / 2,
            width (),
            height ());

    setWindowTitle ("Ortho[*]");
    setWindowIcon (Config::appIcon ());

    ui->addToPersonalDic  ->setDisabled (true);
    ui->ignore            ->setDisabled (true);
    ui->removeWordFromText->setDisabled (true);
    ui->replaceAll        ->setDisabled (true);
    ui->replaceAlways     ->setDisabled (true);

}

//}}} --------------------------------------------------------------------------
//{{{ .void    initMenu () -----------------------------------------------------

//{{{ style constants ----------------------------------------------------------

/*
 * Constant                                    Value Description
 * QStyle::SP_TitleBarMinButton                 1    Minimize button on title bars (e.g., in QMdiSubWindow).
 * QStyle::SP_TitleBarMenuButton                0    Menu button on a title bar.
 * QStyle::SP_TitleBarMaxButton                 2    Maximize button on title bars.
 * QStyle::SP_TitleBarCloseButton               3    Close button on title bars.
 * QStyle::SP_TitleBarNormalButton              4    Normal (restore) button on title bars.
 * QStyle::SP_TitleBarShadeButton               5    Shade button on title bars.
 * QStyle::SP_TitleBarUnshadeButton             6    Unshade button on title bars.
 * QStyle::SP_TitleBarContextHelpButton         7    The Context help button on title bars.
 * QStyle::SP_MessageBoxInformation             9    The "information" icon.
 * QStyle::SP_MessageBoxWarning                10    The "warning" icon.
 * QStyle::SP_MessageBoxCritical               11    The "critical" icon.
 * QStyle::SP_MessageBoxQuestion               12    The "question" icon.
 * QStyle::SP_DesktopIcon                      13    The "desktop" icon.
 * QStyle::SP_TrashIcon                        14    The "trash" icon.
 * QStyle::SP_ComputerIcon                     15    The "My computer" icon.
 * QStyle::SP_DriveFDIcon                      16    The floppy icon.
 * QStyle::SP_DriveHDIcon                      17    The harddrive icon.
 * QStyle::SP_DriveCDIcon                      18    The CD icon.
 * QStyle::SP_DriveDVDIcon                     19    The DVD icon.
 * QStyle::SP_DriveNetIcon                     20    The network icon.
 * QStyle::SP_DirHomeIcon                      55    The home directory icon.
 * QStyle::SP_DirOpenIcon                      21    The open directory icon.
 * QStyle::SP_DirClosedIcon                    22    The closed directory icon.
 * QStyle::SP_DirIcon                          37    The directory icon.
 * QStyle::SP_DirLinkIcon                      23    The link to directory icon.
 * QStyle::SP_FileIcon                         24    The file icon.
 * QStyle::SP_FileLinkIcon                     25    The link to file icon.
 * QStyle::SP_QFileDialogStart                 28    The "start" icon in a file dialog.
 * QStyle::SP_QFileDialogEnd                   29    The "end" icon in a file dialog.
 * QStyle::SP_QFileDialogToParent              30    The "parent directory" icon in a file dialog.
 * QStyle::SP_QFileDialogNewFolder             31    The "create new folder" icon in a file dialog.
 * QStyle::SP_QFileDialogDetailedView          32    The detailed view icon in a file dialog.
 * QStyle::SP_QFileDialogInfoView              33    The file info icon in a file dialog.
 * QStyle::SP_QFileDialogContentsView          34    The contents view icon in a file dialog.
 * QStyle::SP_QFileDialogListView              35    The list view icon in a file dialog.
 * QStyle::SP_QFileDialogBack                  36    The back arrow in a file dialog.
 * QStyle::SP_DockWidgetCloseButton             8    Close button on dock windows (see also QDockWidget).
 * QStyle::SP_ToolBarHorizontalExtensionButton 26    Extension button for horizontal toolbars.
 * QStyle::SP_ToolBarVerticalExtensionButton   27    Extension button for vertical toolbars.
 * QStyle::SP_DialogOkButton                   38    Icon for a standard OK button in a QDialogButtonBox.
 * QStyle::SP_DialogCancelButton               39    Icon for a standard Cancel button in a QDialogButtonBox.
 * QStyle::SP_DialogHelpButton                 40    Icon for a standard Help button in a QDialogButtonBox.
 * QStyle::SP_DialogOpenButton                 41    Icon for a standard Open button in a QDialogButtonBox.
 * QStyle::SP_DialogSaveButton                 42    Icon for a standard Save button in a QDialogButtonBox.
 * QStyle::SP_DialogCloseButton                43    Icon for a standard Close button in a QDialogButtonBox.
 * QStyle::SP_DialogApplyButton                44    Icon for a standard Apply button in a QDialogButtonBox.
 * QStyle::SP_DialogResetButton                45    Icon for a standard Reset button in a QDialogButtonBox.
 * QStyle::SP_DialogDiscardButton              46    Icon for a standard Discard button in a QDialogButtonBox.
 * QStyle::SP_DialogYesButton                  47    Icon for a standard Yes button in a QDialogButtonBox.
 * QStyle::SP_DialogNoButton                   48    Icon for a standard No button in a QDialogButtonBox.
 * QStyle::SP_ArrowUp                          49    Icon arrow pointing up.
 * QStyle::SP_ArrowDown                        50    Icon arrow pointing down.
 * QStyle::SP_ArrowLeft                        51    Icon arrow pointing left.
 * QStyle::SP_ArrowRight                       52    Icon arrow pointing right.
 * QStyle::SP_ArrowBack                        53    Equivalent to SP_ArrowLeft when the current layout direction is Qt::LeftToRight, otherwise SP_ArrowRight.
 * QStyle::SP_ArrowForward                     54    Equivalent to SP_ArrowRight when the current layout direction is Qt::LeftToRight, otherwise SP_ArrowLeft.
 * QStyle::SP_CommandLink                      56    Icon used to indicate a Vista style command link glyph.
 * QStyle::SP_VistaShield                      57    Icon used to indicate UAC prompts on Windows Vista. This will return a null pixmap or icon on all other platforms.
 * QStyle::SP_BrowserReload                    58    Icon indicating that the current page should be reloaded.
 * QStyle::SP_BrowserStop                      59    Icon indicating that the page loading should stop.
 * QStyle::SP_MediaPlay                        60    Icon indicating that media should begin playback.
 * QStyle::SP_MediaStop                        61    Icon indicating that media should stop playback.
 * QStyle::SP_MediaPause                       62    Icon indicating that media should pause playback.
 * QStyle::SP_MediaSkipForward                 63    Icon indicating that media should skip forward.
 * QStyle::SP_MediaSkipBackward                64    Icon indicating that media should skip backward.
 * QStyle::SP_MediaSeekForward                 65    Icon indicating that media should seek forward.
 * QStyle::SP_MediaSeekBackward                66    Icon indicating that media should seek backward.
 * QStyle::SP_MediaVolume                      67    Icon indicating a volume control.
 * QStyle::SP_MediaVolumeMuted                 68    Icon indicating a muted volume control.
 */

//}}} --------------------------------------------------------------------------

void MainWindow::initMenu ()
{
    QStyle * style = qApp->style ();

    ui->actionOpen        ->setIcon (QIcon::fromTheme    ("document-open"            ));
    ui->actionSave        ->setIcon (QIcon::fromTheme    ("document-save"            ));
    ui->actionSaveAs      ->setIcon (QIcon::fromTheme    ("document-save-as"         ));
    ui->actionCopy        ->setIcon (QIcon::fromTheme    ("edit-copy"                ));
    ui->actionCut         ->setIcon (QIcon::fromTheme    ("edit-cut"                 ));
    ui->actionPaste       ->setIcon (QIcon::fromTheme    ("edit-paste"               ));
    ui->actionPreferences ->setIcon (QIcon::fromTheme    ("preferences-desktop"      ));
    //---
    ui->actionShowMessages->setIcon (QIcon::fromTheme    ("mail-mark-read"           ));
    //---
    ui->actionQuit        ->setIcon (QIcon::fromTheme    ("application-exit"         ));
    ui->actionUndo        ->setIcon (QIcon::fromTheme    ("edit-undo"                ));
    ui->actionRedo        ->setIcon (QIcon::fromTheme    ("edit-redo"                ));
    ui->actionAboutQt     ->setIcon (QIcon::fromTheme    ("qtassistant"              ));

    ui->actionHelp        ->setIcon (style->standardIcon (QStyle::SP_DialogHelpButton));
    ui->ignore            ->setIcon (style->standardIcon (QStyle::SP_MediaSeekForward));
    ui->removeWordFromText->setIcon (style->standardIcon (QStyle::SP_TrashIcon       ));
    ui->addToPersonalDic  ->setIcon (QIcon::fromTheme    ("accessories-dictionary"   ));
    ui->replaceAll        ->setIcon (QIcon::fromTheme    ("edit-find-replace"        ));
    ui->replaceAlways     ->setIcon (QIcon::fromTheme    ("edit-find-replace"        ));
}

//}}} --------------------------------------------------------------------------
//{{{ .void    initToolbar () --------------------------------------------------

void MainWindow::initToolbar ()
{
    QWidget * spacer = new QWidget (m_toolBar = ui->mainToolBar);
    spacer->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);

    m_toolBar->addAction (ui->actionOpen        );
    m_toolBar->addAction (ui->actionSave        );
    m_toolBar->addSeparator ();
    m_toolBar->addAction (ui->actionPreferences );
    m_toolBar->addSeparator ();
    m_toolBar->addAction (ui->actionCopy        );
    m_toolBar->addAction (ui->actionCut         );
    m_toolBar->addAction (ui->actionPaste       );
    m_toolBar->addSeparator ();
    m_toolBar->addAction (ui->actionUndo        );
    m_toolBar->addAction (ui->actionRedo        );
    m_toolBar->addSeparator ();
    m_toolBar->addAction (ui->actionShowMessages);
    m_toolBar->addWidget (spacer);
    m_toolBar->addAction (ui->actionQuit        );
}

//}}} --------------------------------------------------------------------------
//{{{ .void    initConnect () --------------------------------------------------

void MainWindow::initConnect ()
{
    connect (m_edit, 
            SIGNAL (copyAvailable (bool)), 
            ui->actionCopy, 
            SLOT (setEnabled (bool)));

    connect (m_edit, 
            SIGNAL (copyAvailable (bool)), 
            ui->actionCut, 
            SLOT (setEnabled (bool)));

    connect (m_edit, 
            SIGNAL (undoAvailable (bool)), 
            ui->actionUndo, 
            SLOT (setEnabled (bool)));

    connect (m_edit, 
            SIGNAL (redoAvailable (bool)), 
            ui->actionRedo, 
            SLOT (setEnabled (bool)));

    connect (ui->actionCopy, 
            SIGNAL (triggered ()), 
            m_edit, 
            SLOT (copy ()));

    connect (ui->actionCut, 
            SIGNAL (triggered ()), 
            m_edit, 
            SLOT (cut ()));

    connect (ui->actionPaste, 
            SIGNAL (triggered ()), 
            m_edit, 
            SLOT (paste ()));

    connect (ui->actionUndo, 
            SIGNAL (triggered ()), 
            m_edit, 
            SLOT (undo ()));

    connect (ui->actionRedo, 
            SIGNAL (triggered ()), 
            m_edit, 
            SLOT (redo ()));

    connect (ui->unknownList, 
            SIGNAL (currentTextChanged (QString)), 
            this, 
            SLOT (onUnknownListCurrentTextChanged (QString)));

    connect (m_ortho, 
            SIGNAL (message (QString)), 
            this, 
            SLOT (onMessage (QString)));
}

//}}} --------------------------------------------------------------------------
//{{{ .void    initDocument () -------------------------------------------------

// Les druides étaient capables de lire l'avenir d'un homme dans ses propres entrailles. Ils ne se trompaient jamais."

void MainWindow::initDocument ()
{
    m_doc  = new QTextDocument (this);
    m_edit = ui->edit;
    m_edit->setAcceptRichText (true);
    m_edit->setDocument (m_doc);
}

//}}} --------------------------------------------------------------------------
//{{{ .void    open (const QString & path) -------------------------------------

void MainWindow::open (const QString & path)
{
    QString result;

    if (path.isEmpty ())
    {
        setWindowTitle (tr ("(sans nom)[*] - Ortho"));
        return;
    }

    QFile file (path);
    if (file.exists () && file.open (QIODevice::ReadOnly | QIODevice::Text))
    {
        QTextStream in (& file);
        result = in.readAll ();
    }
    m_doc->setPlainText (result);
    m_doc->setModified (false);
    setWindowTitle ("");
    setWindowFilePath (path);
    setWindowModified (false);

    ui->actionCopy->setDisabled (true);
    ui->actionCut ->setDisabled (true);
    ui->actionUndo->setDisabled (true);
    ui->actionRedo->setDisabled (true);

    onMessage (tr ("Chargement de %1").arg (path));
}

//}}} --------------------------------------------------------------------------
//{{{ .void    changeEvent (QEvent * e) ----------------------------------------

void MainWindow::changeEvent (QEvent * e)
{
    QMainWindow::changeEvent (e);
    switch (e->type ())
    {
    case QEvent::LanguageChange :
        ui->retranslateUi (this);
        break;
    default:
        break;
    }
}

//}}} --------------------------------------------------------------------------
//{{{ .QString selectedUnknownWord () ------------------------------------------

QString MainWindow::selectedUnknownWord ()
{
    QList<QListWidgetItem*> selection (ui->unknownList->selectedItems ());
    return (selection.isEmpty () ? QString () : selection.at (0)->text ());
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_ignore_clicked () --------------------------------------------

void MainWindow::on_ignore_clicked ()
{
    m_ortho->addToIgnoreList (selectedUnknownWord ());
    on_edit_textChanged ();
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_addToPersonalDic_clicked () ----------------------------------

void MainWindow::on_addToPersonalDic_clicked ()
{
    m_ortho->addLineToPersonalDic (selectedUnknownWord ());
    on_edit_textChanged ();
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_replaceAlways_clicked () -------------------------------------

void MainWindow::on_replaceAlways_clicked ()
{
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_replaceAll_clicked () ----------------------------------------

void MainWindow::on_replaceAll_clicked ()
{
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_removeWordFromText_clicked () --------------------------------

void MainWindow::on_removeWordFromText_clicked ()
{
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_actionAboutQt_triggered () -----------------------------------

void MainWindow::on_actionAboutQt_triggered ()
{
    QApplication::aboutQt ();
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_actionPreferences_triggered () -------------------------------

void MainWindow::on_actionPreferences_triggered ()
{
    // __ns__: replaced pointer by plain variable
    // why allocate ???

    Preferences pref (this);
    pref.exec ();
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_actionOpen_triggered () --------------------------------------

void MainWindow::on_actionOpen_triggered ()
{
    QString path = QFileDialog::getOpenFileName (this, tr ("Ouvrir le document"));

    open (path);
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_edit_textChanged () ------------------------------------------

void MainWindow::on_edit_textChanged ()
{
    setWindowModified (true);
    ui->unknownList->clear ();
    ui->unknownList->addItems (m_ortho->unknownWords (m_edit->toPlainText ()));
    if (false) ui->unknownList->setCurrentRow (0);
}

//}}} --------------------------------------------------------------------------
//{{{ .void    on_actionShowMessages_triggered () ------------------------------

void MainWindow::on_actionShowMessages_triggered ()
{
    ui->actionShowMessages->setIcon (QIcon::fromTheme ("mail-mark-read"));

    // __ns__: replaced pointer by plain variable
    // why allocate ???

    Messages msg (this);
    msg.setMessageList (m_messages);
    msg.exec ();

    ui->actionShowMessages->setEnabled (! m_messages.isEmpty ());
}

//}}} --------------------------------------------------------------------------
//{{{ .void    onUnknownListCurrentTextChanged (const QString & word) ----------

void MainWindow::onUnknownListCurrentTextChanged (const QString & word)
{
    ui->addToPersonalDic->setDisabled (word.isEmpty ());
    ui->ignore->setDisabled (word.isEmpty ());
    ui->removeWordFromText->setDisabled (word.isEmpty ());

    ui->suggestionList->clear ();
    ui->suggestionList->addItems (m_ortho->suggestsFor (word));
}

//}}} --------------------------------------------------------------------------
//{{{ .void    onMessage (const QString & msg) ---------------------------------

void MainWindow::onMessage (const QString & msg)
{
    m_messages << msg;
    ui->actionShowMessages->setIcon (QIcon::fromTheme ("mail-mark-unread"));
    ui->actionShowMessages->setEnabled (true);
}

//}}} --------------------------------------------------------------------------

